;;;
;;; Character type parent - Inherits from Thing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (character n)
	(let ((type 'character)								;Identifier
		  (super (thing n)))
	(define this
		(lambda (msg)
			(cond ((eq? msg 'getType) type) 			;Return character's type
				  (else (super msg)))
		)
	)
	this)
)

(define (player n p)
	(let ((place p)
			(inventory '())
			(equipment '())
		  	(type 'player)
			(super (character n)))
	(define take
		(lambda (obj)
			(cond ((not(eq? 'room (place 'getType)))
						(print-message "You can't take things from here"))
					((eq? obj 'everything)
						(if (null? (place 'getObjects))
							(print-message "There are no object's in this place.")
							(begin
								(set! inventory (cons (place 'getObjects) inventory))
								(forall (place 'getObjects)
									(lambda (o)
										(begin
											(print-message (list (o 'getName) " added to inventory"))
											((place 'removeObject) o)
										)
									)
								)
							)
						))
					((memq obj (place 'getObjects))
						(begin
							(print-message (list (o 'getName) " added to inventory"))
							(set! inventory (cons obj inventory))
							((place 'removeObject) obj)
							nil
						))
					(else (print-message "Object not found in this place"))
			)
		)
	)
	(define dropObject
		(lambda (obj)
			(if (memq obj inventory)
				(begin
					(begin (delete obj inventory)
						(if (memq obj equipment)
							(begin (delete obj equipment)
								(print-message (list (obj 'getName) " unequiped."))
							)
						)
						(print-message (list (obj 'getName) " dropped."))
						(if (eq? 'room (place 'getType))
							((place 'addObject) obj)
						)
					)
				)
			)
		)
	)
	(define go
		(lambda (direction)
			(let ((new-place ((place 'getNeighbor) direction)))
				(if (not (null? new-place))
					(begin 
						;(newline)
						;(display "Moved from ") (display (place 'getName))
						;(display " to ") (display (new-place 'getName))
						(print-message (list "Moved from " (place 'getName) " to " (new-place 'getName)))
						(set! place new-place)
						nil
					)
					(print-message "Can't go that way.")
				)
			)
		)
	)
	(define equip
		(lambda (obj)
			(if (memq obj inventory)
				(let ((tmpType (obj 'getType))
					  (tmpItem '()))
					(if (or (eq? tmpType 'weapon) (eq? tmpType 'armor) (eq? tmpType 'accesory))
						(begin (forall (filter equipment
										(lambda (el)
											(eq? (el 'getType) tmpType)
										))
								(lambda (el)
									(set! tmpItem (cons el tmpItem))
								))
							(if (null? tmpItem)
								(begin (set! equipment (cons obj equipment))
									(print-message (list (obj 'getName) " equiped."))
								)
								(begin
									(delete (car tmpItem) equipment)
									(set! equipment (cons obj equipment))
									(print-message (list (obj 'getName) " equiped."))
								)
							)
						)
						
						(begin (newline) (display "Can't equip that type of item")nil)
					)
				)
				(begin (newline) (display (obj 'getName)) (display " not in the inventory.")nil)
			)
		)
	)
	(define endGame
		(lambda ()
			(quit)
		)
	)
	(define this
		(lambda (msg)
			(cond ((eq? msg 'getType) type)
				  ((eq? msg 'getPlace) place)			;Return character's location
				  ((eq? msg 'take) take)
				  ((eq? msg 'dropObject) dropObject)
				  ((eq? msg 'equip) equip)
				  ((eq? msg 'go) go)
				  ((eq? msg 'getInventory) inventory)
				  ((eq? msg 'getEquipment) equipment)
				  ((eq? msg 'endGame) endGame)
				  (else (super msg)))
		)	
	)
	this)
)